package com.utbm.lo54.dao.neo4j;

import java.util.Date;
import java.util.Set;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.Transaction;

import com.utbm.lo54.dao.SessionDAOInterface;
import com.utbm.lo54.entity.Course;
import com.utbm.lo54.entity.Location;
import com.utbm.lo54.entity.Session;

public class Neo4jSessionDAO implements SessionDAOInterface{

	@Override
	public Session create(Session se) {
		Node firstNode;
		Node courseNode;
		Node locNode;
		GraphDatabaseService graphDb = Neo4jUtility.getGraphDatabase();

		Transaction tx = graphDb.beginTx();
		try
		{
			
			Node foundNode=Neo4jUtility.getNodeIndex().get("STARTDATE", se.getStartDate()).getSingle();
			if (foundNode!=null) return nodeToSession(foundNode);
			firstNode = Neo4jUtility.createAndIndex("STARTDATE", ""+se.getStartDate());
			sessionToNode(se,firstNode);
			se.setId(firstNode.getId());
			
			courseNode=Neo4jUtility.getNodeIndex().get("CODE", se.getCourseCode()).getSingle();
			locNode=graphDb.getNodeById(se.getLocationId());
			
			firstNode.createRelationshipTo(courseNode, Neo4jUtility.RelTypes.PLANNED);
			firstNode.createRelationshipTo(locNode, Neo4jUtility.RelTypes.LOCATED);
			
			tx.success();
		}
		finally
		{
			tx.finish();
		}
		return se;
	}

	private void sessionToNode(Session se, Node firstNode) {
		firstNode.setProperty(SessionProperties.STARTDATE.name(), se.getStartDate().getTime());
		firstNode.setProperty(SessionProperties.ENDDATE.name(), se.getEndDate().getTime());
		firstNode.setProperty(SessionProperties.TYPE.name(), "SESSION");
	}

	private Session nodeToSession(Node foundNode) {
		Session se = new Session();
		se.setId(foundNode.getId());
		se.setEndDate(new Date((Long.parseLong(foundNode.getProperty(SessionProperties.ENDDATE.name()).toString()))));
		se.setStartDate(new Date(Long.parseLong(foundNode.getProperty(SessionProperties.STARTDATE.name()).toString())));
		for(Relationship re :foundNode.getRelationships(Neo4jUtility.RelTypes.PLANNED)){
			Node course = re.getOtherNode(foundNode);
			se.setCourseCode(Neo4jCourseDAO.nodeToCourse(course).getCode());
		}
		for(Relationship re :foundNode.getRelationships(Neo4jUtility.RelTypes.LOCATED)){
			Node loc = re.getOtherNode(foundNode);
			se.setLocationId(loc.getId());
		}
		return se;
	}

	@Override
	public void delete(Session se) {
		Node sessionNode;
		GraphDatabaseService graphDb = Neo4jUtility.getGraphDatabase();
		Transaction tx = graphDb.beginTx();
		try
		{
			sessionNode = graphDb.getNodeById(se.getId());
			Neo4jUtility.getNodeIndex().remove(sessionNode);
			Iterable<Relationship> rels = sessionNode.getRelationships();
			for(Relationship rel : rels){
				rel.delete();
			}
			sessionNode.delete();			
			tx.success();
		}
		finally
		{
			tx.finish();
		}
		
	}


	@Override
	public Session findById(Long id) {
		Node sessionNode;
		GraphDatabaseService graphDb = Neo4jUtility.getGraphDatabase();
		Transaction tx = graphDb.beginTx();
		try
		{
			sessionNode = graphDb.getNodeById(id);
			tx.success();
		}
		finally
		{
			tx.finish();
		}
		return nodeToSession(sessionNode);
	}

	@Override
	public Session findByDate(Date begin, Date end) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void update(Session se) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Set<Session> getAllSession() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Set<Session> findByCourse(String code) {
		// TODO Auto-generated method stub
		return null;
	}

}
